

#include "loop.h"
#include "./../io_reuse_module/io_reuse_module_define.h"
#include "./../channel/channel.h"

#include <memory>
#include <thread>
#include <vector>

Loop::Loop()
{
    IoEpollFactory factory;
    m_ioreuse_module = std::make_shared<IoReuseModule>(&factory);
}

Loop::Loop(IoReuseModuleFactory * factory)
{
    m_ioreuse_module = std::make_shared<IoReuseModule>(factory);
}

Loop::~Loop()
{
    m_status = false;
}

void Loop::Run()
{
    m_status    = true;
    m_thread_id = std::this_thread::get_id();
    while (m_status)
    {
        int wait_time = -1;
        if (!m_channel_post_task.empty())
        {
            wait_time = 0;
        }
        std::vector<::EventData>      trigger_data_vec;
        int                           trigger_size = m_ioreuse_module->WaitEvent(trigger_data_vec, wait_time);
        if (trigger_size > 0)
        {
            for (auto & data : trigger_data_vec)
            {
                m_channel_protocol_map[data.id]->OnEvent(data);
            }
        }
        if (!m_channel_post_task.empty())
        {
            EventData event = {};
            for (auto & data : m_channel_post_task)
            {
                event.id     = data->Index();
                event.events = EmIoPost;
                data->OnEvent(event);
            }
            m_channel_post_task.clear();
        }
        if (m_channel_protocol_map.empty() && m_channel_post_task.empty())
        {
            m_status = false;
        }
    }
}

bool Loop::AddEvent(const std::shared_ptr<ChannelProtocol>& channel, int event)
{
    int64_t index = m_ioreuse_module->AddEvent(channel->DescriptionData(), event);
    if (index <= 0)
    {
        return false;
    }
    channel->Index(index);
    m_channel_protocol_map[index] = channel;
    return true;
}

bool Loop::ModEvent(int64_t index, int event) const
{
    int64_t result = m_ioreuse_module->ModEvent(index, event);
    return result >= 0 ? true : false;
}

bool Loop::DelEvent(int64_t index)
{
    m_ioreuse_module->DelEvent(index);
    m_channel_protocol_map.erase(index);
    return true;
}

bool Loop::AddPostTask(const std::shared_ptr<ChannelProtocol> & channel)
{
    m_channel_post_task.push_back(channel);
    return true;
}
